package darknet

// import (
// 	"context"
// 	"crypto/tls"
// 	"encoding/base64"
// 	"errors"
// 	"fmt"
// 	"io"
// 	"log"
// 	"net"
// 	"net/http"
// 	"net/url"
// 	"reflect"
// 	"sort"
// 	"strings"
// 	"sync"
// 	"sync/atomic"
// 	"time"
// 	"unicode"

// 	"golang.org/x/net/idna"
// )

// var ErrUseLastResponse = errors.New("net/http: use last response")

// var portMap = map[string]string{
// 	"http":   "80",
// 	"https":  "443",
// 	"socks5": "1080",
// }

// func cloneOrMakeHeader(hdr http.Header) http.Header {
// 	clone := hdr.Clone()
// 	if clone == nil {
// 		clone = make(http.Header)
// 	}
// 	return clone
// }
// func idnaASCII(v string) (string, error) {
// 	// TODO: Consider removing this check after verifying performance is okay.
// 	// Right now punycode verification, length checks, context checks, and the
// 	// permissible character tests are all omitted. It also prevents the ToASCII
// 	// call from salvaging an invalid IDN, when possible. As a result it may be
// 	// possible to have two IDNs that appear identical to the user where the
// 	// ASCII-only version causes an error downstream whereas the non-ASCII
// 	// version does not.
// 	// Note that for correct ASCII IDNs ToASCII will only do considerably more
// 	// work, but it will not cause an allocation.

// 	if ascciiis(v) {
// 		return v, nil
// 	}
// 	return idna.Lookup.ToASCII(v)
// }

// func ascciiis(s string) bool {
// 	for i := 0; i < len(s); i++ {
// 		if s[i] > unicode.MaxASCII {
// 			return false
// 		}
// 	}
// 	return true
// }

// // canonicalAddr returns url.Host but always with a ":port" suffix
// func canonicalAddr(url *url.URL) string {
// 	addr := url.Hostname()
// 	if v, err := idnaASCII(addr); err == nil {
// 		addr = v
// 	}
// 	port := url.Port()
// 	if port == "" {
// 		port = portMap[url.Scheme]
// 	}
// 	return net.JoinHostPort(addr, port)
// }

// // isDomainOrSubdomain reports whether sub is a subdomain (or exact
// // match) of the parent domain.
// //
// // Both domains must already be in canonical form.
// func isDomainOrSubdomain(sub, parent string) bool {
// 	if sub == parent {
// 		return true
// 	}
// 	// If sub is "foo.example.com" and parent is "example.com",
// 	// that means sub must end in "."+parent.
// 	// Do it without allocating.
// 	if !strings.HasSuffix(sub, parent) {
// 		return false
// 	}
// 	return sub[len(sub)-len(parent)-1] == '.'
// }

// func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool {
// 	switch http.CanonicalHeaderKey(headerKey) {
// 	case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
// 		// Permit sending auth/cookie headers from "foo.com"
// 		// to "sub.foo.com".

// 		// Note that we don't send all cookies to subdomains
// 		// automatically. This function is only used for
// 		// Cookies set explicitly on the initial outgoing
// 		// client request. Cookies automatically added via the
// 		// CookieJar mechanism continue to follow each
// 		// cookie's scope as set by Set-Cookie. But for
// 		// outgoing requests with the Cookie header set
// 		// directly, we don't know their scope, so we assume
// 		// it's for *.domain.com.

// 		ihost := canonicalAddr(initial)
// 		dhost := canonicalAddr(dest)
// 		return isDomainOrSubdomain(dhost, ihost)
// 	}
// 	// All other headers are copied:
// 	return true
// }

// func makeHeadersCopier(c *http.Client, ireq *http.Request) func(*http.Request) {

// 	// The headers to copy are from the very initial request.
// 	// We use a closured callback to keep a reference to these original headers.
// 	var (
// 		ireqhdr  = cloneOrMakeHeader(ireq.Header)
// 		icookies map[string][]*http.Cookie
// 	)
// 	if c.Jar != nil && ireq.Header.Get("Cookie") != "" {
// 		icookies = make(map[string][]*http.Cookie)
// 		for _, c := range ireq.Cookies() {
// 			icookies[c.Name] = append(icookies[c.Name], c)
// 		}
// 	}

// 	preq := ireq // The previous request
// 	return func(req *http.Request) {
// 		// If Jar is present and there was some initial cookies provided
// 		// via the request header, then we may need to alter the initial
// 		// cookies as we follow redirects since each redirect may end up
// 		// modifying a pre-existing cookie.
// 		//
// 		// Since cookies already set in the request header do not contain
// 		// information about the original domain and path, the logic below
// 		// assumes any new set cookies override the original cookie
// 		// regardless of domain or path.
// 		//
// 		// See https://golang.org/issue/17494
// 		if c.Jar != nil && icookies != nil {
// 			var changed bool
// 			resp := req.Response // The response that caused the upcoming redirect
// 			for _, c := range resp.Cookies() {
// 				if _, ok := icookies[c.Name]; ok {
// 					delete(icookies, c.Name)
// 					changed = true
// 				}
// 			}
// 			if changed {
// 				ireqhdr.Del("Cookie")
// 				var ss []string
// 				for _, cs := range icookies {
// 					for _, c := range cs {
// 						ss = append(ss, c.Name+"="+c.Value)
// 					}
// 				}
// 				sort.Strings(ss) // Ensure deterministic headers
// 				ireqhdr.Set("Cookie", strings.Join(ss, "; "))
// 			}
// 		}

// 		// Copy the initial request's Header values
// 		// (at least the safe ones).
// 		for k, vv := range ireqhdr {
// 			if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) {
// 				req.Header[k] = vv
// 			}
// 		}

// 		preq = req // Update previous Request with the current request
// 	}

// }

// func closeBodyReq(r *http.Request) error {
// 	if r.Body == nil {
// 		return nil
// 	}
// 	return r.Body.Close()
// }

// func closeBodyRes(r *http.Response) error {
// 	if r.Body == nil {
// 		return nil
// 	}
// 	return r.Body.Close()
// }

// func stripPassword(u *url.URL) string {
// 	_, passSet := u.User.Password()
// 	if passSet {
// 		return strings.Replace(u.String(), u.User.String()+"@", u.User.Username()+":***@", 1)
// 	}
// 	return u.String()
// }

// // urlErrorOp returns the (*url.Error).Op value to use for the
// // provided (*Request).Method value.
// func urlErrorOp(method string) string {
// 	if method == "" {
// 		return "Get"
// 	}
// 	if lowerMethod, ok := ToLower(method); ok {
// 		return method[:1] + lowerMethod[1:]
// 	}
// 	return method
// }

// // ToLower returns the lowercase version of s if s is ASCII and printable.
// func ToLower(s string) (lower string, ok bool) {
// 	if !IsPrint(s) {
// 		return "", false
// 	}
// 	return strings.ToLower(s), true
// }

// // IsPrint returns whether s is ASCII and printable according to
// // https://tools.ietf.org/html/rfc20#section-4.2.
// func IsPrint(s string) bool {
// 	for i := 0; i < len(s); i++ {
// 		if s[i] < ' ' || s[i] > '~' {
// 			return false
// 		}
// 	}
// 	return true
// }

// // refererForURL returns a referer without any authentication info or
// // an empty string if lastReq scheme is https and newReq scheme is http.
// func refererForURL(lastReq, newReq *url.URL) string {
// 	// https://tools.ietf.org/html/rfc7231#section-5.5.2
// 	//   "Clients SHOULD NOT include a Referer header field in a
// 	//    (non-secure) HTTP request if the referring page was
// 	//    transferred with a secure protocol."
// 	if lastReq.Scheme == "https" && newReq.Scheme == "http" {
// 		return ""
// 	}
// 	referer := lastReq.String()
// 	if lastReq.User != nil {
// 		// This is not very efficient, but is the best we can
// 		// do without:
// 		// - introducing a new method on URL
// 		// - creating a race condition
// 		// - copying the URL struct manually, which would cause
// 		//   maintenance problems down the line
// 		auth := lastReq.User.String() + "@"
// 		referer = strings.Replace(referer, auth, "", 1)
// 	}
// 	return referer
// }

// func defaultCheckRedirect(req *http.Request, via []*http.Request) error {
// 	if len(via) >= 10 {
// 		return errors.New("stopped after 10 redirects")
// 	}
// 	return nil
// }

// // checkRedirect calls either the user's configured CheckRedirect
// // function, or the default.
// func checkRedirect(c *http.Client, req *http.Request, via []*http.Request) error {
// 	fn := c.CheckRedirect
// 	if fn == nil {
// 		fn = defaultCheckRedirect
// 	}
// 	return fn(req, via)
// }

// func transport(c *http.Client) http.RoundTripper {
// 	if c.Transport != nil {
// 		return c.Transport
// 	}
// 	return http.DefaultTransport
// }

// // didTimeout is non-nil only if err != nil.
// func csend(c *http.Client, req *http.Request, deadline time.Time) (resp *http.Response, didTimeout func() bool, err error) {
// 	if c.Jar != nil {
// 		for _, cookie := range c.Jar.Cookies(req.URL) {
// 			req.AddCookie(cookie)
// 		}
// 	}
// 	resp, didTimeout, err = send(req, transport(c), deadline)
// 	if err != nil {
// 		return nil, didTimeout, err
// 	}
// 	if c.Jar != nil {
// 		if rc := resp.Cookies(); len(rc) > 0 {
// 			c.Jar.SetCookies(req.URL, rc)
// 		}
// 	}
// 	return resp, nil, nil
// }
// func alwaysFalse() bool { return false }

// // cancelTimerBody is an io.ReadCloser that wraps rc with two features:
// // 1) On Read error or close, the stop func is called.
// // 2) On Read failure, if reqDidTimeout is true, the error is wrapped and
// //    marked as net.Error that hit its timeout.
// type cancelTimerBody struct {
// 	stop          func() // stops the time.Timer waiting to cancel the request
// 	rc            io.ReadCloser
// 	reqDidTimeout func() bool
// }

// // It is not meant to be urlencoded.
// func basicAuth(username, password string) string {
// 	auth := username + ":" + password
// 	return base64.StdEncoding.EncodeToString([]byte(auth))
// }

// // Caller should close resp.Body when done reading from it.
// func send(ireq *http.Request, rt http.RoundTripper, deadline time.Time) (resp *http.Response, didTimeout func() bool, err error) {
// 	req := ireq // req is either the original request, or a modified fork

// 	if rt == nil {
// 		closeBodyReq(req)
// 		return nil, alwaysFalse, errors.New("http: no Client.Transport or DefaultTransport")
// 	}

// 	if req.URL == nil {
// 		closeBodyReq(req)
// 		return nil, alwaysFalse, errors.New("http: nil Request.URL")
// 	}

// 	if req.RequestURI != "" {
// 		closeBodyReq(req)
// 		return nil, alwaysFalse, errors.New("http: Request.RequestURI can't be set in client requests")
// 	}

// 	// forkReq forks req into a shallow clone of ireq the first
// 	// time it's called.
// 	forkReq := func() {
// 		if ireq == req {
// 			req = new(http.Request)
// 			*req = *ireq // shallow clone
// 		}
// 	}

// 	// Most the callers of send (Get, Post, et al) don't need
// 	// Headers, leaving it uninitialized. We guarantee to the
// 	// Transport that this has been initialized, though.
// 	if req.Header == nil {
// 		forkReq()
// 		req.Header = make(http.Header)
// 	}

// 	if u := req.URL.User; u != nil && req.Header.Get("Authorization") == "" {
// 		username := u.Username()
// 		password, _ := u.Password()
// 		forkReq()
// 		req.Header = cloneOrMakeHeader(ireq.Header)
// 		req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
// 	}

// 	if !deadline.IsZero() {
// 		forkReq()
// 	}
// 	stopTimer, didTimeout := setRequestCancel(req, rt, deadline)

// 	resp, err = rt.RoundTrip(req)
// 	if err != nil {
// 		stopTimer()
// 		if resp != nil {
// 			log.Printf("RoundTripper returned a response & error; ignoring response")
// 		}
// 		if tlsErr, ok := err.(tls.RecordHeaderError); ok {
// 			// If we get a bad TLS record header, check to see if the
// 			// response looks like HTTP and give a more helpful error.
// 			// See golang.org/issue/11111.
// 			if string(tlsErr.RecordHeader[:]) == "HTTP/" {
// 				err = errors.New("http: server gave HTTP response to HTTPS client")
// 			}
// 		}
// 		return nil, didTimeout, err
// 	}
// 	if resp == nil {
// 		return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a nil *Response with a nil error", rt)
// 	}
// 	if resp.Body == nil {
// 		// The documentation on the Body field says “The http Client and Transport
// 		// guarantee that Body is always non-nil, even on responses without a body
// 		// or responses with a zero-length body.” Unfortunately, we didn't document
// 		// that same constraint for arbitrary RoundTripper implementations, and
// 		// RoundTripper implementations in the wild (mostly in tests) assume that
// 		// they can use a nil Body to mean an empty one (similar to Request.Body).
// 		// (See https://golang.org/issue/38095.)
// 		//
// 		// If the ContentLength allows the Body to be empty, fill in an empty one
// 		// here to ensure that it is non-nil.
// 		if resp.ContentLength > 0 && req.Method != "HEAD" {
// 			return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a *Response with content length %d but a nil Body", rt, resp.ContentLength)
// 		}
// 		resp.Body = io.NopCloser(strings.NewReader(""))
// 	}
// 	if !deadline.IsZero() {
// 		resp.Body = &cancelTimerBody{
// 			stop:          stopTimer,
// 			rc:            resp.Body,
// 			reqDidTimeout: didTimeout,
// 		}
// 	}
// 	return resp, nil, nil
// }

// func nop() {}

// type atomicBool int32

// func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
// func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
// func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }

// // setRequestCancel sets req.Cancel and adds a deadline context to req
// // if deadline is non-zero. The RoundTripper's type is used to
// // determine whether the legacy CancelRequest behavior should be used.
// //
// // As background, there are three ways to cancel a request:
// // First was Transport.CancelRequest. (deprecated)
// // Second was Request.Cancel.
// // Third was Request.Context.
// // This function populates the second and third, and uses the first if it really needs to.
// func setRequestCancel(req *http.Request, rt http.RoundTripper, deadline time.Time) (stopTimer func(), didTimeout func() bool) {
// 	if deadline.IsZero() {
// 		return nop, alwaysFalse
// 	}
// 	knownTransport := knownRoundTripperImpl(rt, req)
// 	oldCtx := req.Context()

// 	if req.Cancel == nil && knownTransport {
// 		// If they already had a Request.Context that's
// 		// expiring sooner, do nothing:
// 		if !timeBeforeContextDeadline(deadline, oldCtx) {
// 			return nop, alwaysFalse
// 		}

// 		var cancelCtx func()
// 		var ctx context.Context
// 		ctx, cancelCtx = context.WithDeadline(oldCtx, deadline)
// 		req = req.WithContext(ctx)
// 		return cancelCtx, func() bool { return time.Now().After(deadline) }
// 	}
// 	initialReqCancel := req.Cancel // the user's original Request.Cancel, if any

// 	var cancelCtx func()
// 	if oldCtx := req.Context(); timeBeforeContextDeadline(deadline, oldCtx) {
// 		var ctx context.Context
// 		ctx, cancelCtx = context.WithDeadline(oldCtx, deadline)
// 		req = req.WithContext(ctx)
// 	}

// 	cancel := make(chan struct{})
// 	req.Cancel = cancel

// 	doCancel := func() {
// 		// The second way in the func comment above:
// 		close(cancel)
// 		// The first way, used only for RoundTripper
// 		// implementations written before Go 1.5 or Go 1.6.
// 		type canceler interface{ CancelRequest(*http.Request) }
// 		if v, ok := rt.(canceler); ok {
// 			v.CancelRequest(req)
// 		}
// 	}

// 	stopTimerCh := make(chan struct{})
// 	var once sync.Once
// 	stopTimer = func() {
// 		once.Do(func() {
// 			close(stopTimerCh)
// 			if cancelCtx != nil {
// 				cancelCtx()
// 			}
// 		})
// 	}

// 	timer := time.NewTimer(time.Until(deadline))
// 	var timedOut atomicBool

// 	go func() {
// 		select {
// 		case <-initialReqCancel:
// 			doCancel()
// 			timer.Stop()
// 		case <-timer.C:
// 			timedOut.setTrue()
// 			doCancel()
// 		case <-stopTimerCh:
// 			timer.Stop()
// 		}
// 	}()

// 	return stopTimer, timedOut.isSet
// }

// // EqualFold is strings.EqualFold, ASCII only. It reports whether s and t
// // are equal, ASCII-case-insensitively.
// func EqualFold(s, t string) bool {
// 	if len(s) != len(t) {
// 		return false
// 	}
// 	for i := 0; i < len(s); i++ {
// 		if lower(s[i]) != lower(t[i]) {
// 			return false
// 		}
// 	}
// 	return true
// }

// // lower returns the ASCII lowercase version of b.
// func lower(b byte) byte {
// 	if 'A' <= b && b <= 'Z' {
// 		return b + ('a' - 'A')
// 	}
// 	return b
// }

// // hasToken reports whether token appears with v, ASCII
// // case-insensitive, with space or comma boundaries.
// // token must be all lowercase.
// // v may contain mixed cased.
// func hasToken(v, token string) bool {
// 	if len(token) > len(v) || token == "" {
// 		return false
// 	}
// 	if v == token {
// 		return true
// 	}
// 	for sp := 0; sp <= len(v)-len(token); sp++ {
// 		// Check that first character is good.
// 		// The token is ASCII, so checking only a single byte
// 		// is sufficient. We skip this potential starting
// 		// position if both the first byte and its potential
// 		// ASCII uppercase equivalent (b|0x20) don't match.
// 		// False positives ('^' => '~') are caught by EqualFold.
// 		if b := v[sp]; b != token[0] && b|0x20 != token[0] {
// 			continue
// 		}
// 		// Check that start pos is on a valid token boundary.
// 		if sp > 0 && !isTokenBoundary(v[sp-1]) {
// 			continue
// 		}
// 		// Check that end pos is on a valid token boundary.
// 		if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
// 			continue
// 		}
// 		if EqualFold(v[sp:sp+len(token)], token) {
// 			return true
// 		}
// 	}
// 	return false
// }

// func isTokenBoundary(b byte) bool {
// 	return b == ' ' || b == ',' || b == '\t'
// }

// // requiresHTTP1 reports whether this request requires being sent on
// // an HTTP/1 connection.
// func requiresHTTP1(r *http.Request) bool {
// 	return hasToken(r.Header.Get("Connection"), "upgrade") &&
// 		EqualFold(r.Header.Get("Upgrade"), "websocket")
// }

// func useRegisteredProtocol(t *http.Transport, req *http.Request) bool {
// 	if req.URL.Scheme == "https" && requiresHTTP1(req) {
// 		// If this request requires HTTP/1, don't use the
// 		// "https" alternate protocol, which is used by the
// 		// HTTP/2 code to take over requests if there's an
// 		// existing cached HTTP/2 connection.
// 		return false
// 	}
// 	return true
// }

// // alternateRoundTripper returns the alternate RoundTripper to use
// // for this request if the Request's URL scheme requires one,
// // or nil for the normal case of using the Transport.
// func alternateRoundTripper(t *http.Transport, req *http.Request) http.RoundTripper {
// 	if !useRegisteredProtocol(t, req) {
// 		return nil
// 	}
// 	altProto, _ := t.altProto.Load().(map[string]RoundTripper)
// 	return altProto[req.URL.Scheme]
// }

// // timeBeforeContextDeadline reports whether the non-zero Time t is
// // before ctx's deadline, if any. If ctx does not have a deadline, it
// // always reports true (the deadline is considered infinite).
// func timeBeforeContextDeadline(t time.Time, ctx context.Context) bool {
// 	d, ok := ctx.Deadline()
// 	if !ok {
// 		return true
// 	}
// 	return t.Before(d)
// }

// // knownRoundTripperImpl reports whether rt is a RoundTripper that's
// // maintained by the Go team and known to implement the latest
// // optional semantics (notably contexts). The Request is used
// // to check whether this particular request is using an alternate protocol,
// // in which case we need to check the RoundTripper for that protocol.
// func knownRoundTripperImpl(rt http.RoundTripper, req *http.Request) bool {
// 	switch t := rt.(type) {
// 	case *http.Transport:
// 		if altRT := alternateRoundTripper(t, req); altRT != nil {
// 			return knownRoundTripperImpl(altRT, req)
// 		}
// 		return true
// 	case *http2Transport, http2noDialH2RoundTripper:
// 		return true
// 	}
// 	// There's a very minor chance of a false positive with this.
// 	// Instead of detecting our golang.org/x/net/http2.Transport,
// 	// it might detect a Transport type in a different http2
// 	// package. But I know of none, and the only problem would be
// 	// some temporarily leaked goroutines if the transport didn't
// 	// support contexts. So this is a good enough heuristic:
// 	if reflect.TypeOf(rt).String() == "*http2.Transport" {
// 		return true
// 	}
// 	return false
// }
